package org.dromara.llm.stt.factory;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.llm.domain.LlmConfigType;
import org.dromara.llm.domain.SysLlmConfig;
import org.dromara.llm.service.ISysLlmConfigService;
import org.dromara.llm.stt.SttService;
import org.dromara.llm.stt.providers.*;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@RequiredArgsConstructor
@Component
@Slf4j
public class SttServiceFactory {
    // 默认服务提供商名称
    private static final String DEFAULT_PROVIDER = "vosk";
    // 缓存已初始化的服务：对于API服务，键为"provider:configId"格式；对于本地服务，键为provider名称
    private final Map<String, SttService> serviceCache = new ConcurrentHashMap<>();
    // 标记Vosk是否初始化成功
    private boolean voskInitialized = false;
    // 服务配置服务
    private final ISysLlmConfigService sysLlmConfigService;

    /**
     * 应用启动时自动初始化Vosk服务
     */
//    @PostConstruct
    public void initializeDefaultSttService() {
        log.info("正在初始化默认语音识别服务(Vosk)...");
        initializeVosk();
        if (voskInitialized) {
            log.info("默认语音识别服务(Vosk)初始化成功，可直接使用");
        } else {
            log.warn("默认语音识别服务(Vosk)初始化失败，将在需要时尝试使用备选服务");
        }
    }

    /**
     * 初始化Vosk服务
     */
    private synchronized void initializeVosk() {
        if (serviceCache.containsKey(DEFAULT_PROVIDER)) {
            return;
        }
        try {
            VoskSttService voskService = new VoskSttService();
            voskService.initialize();
            serviceCache.put(DEFAULT_PROVIDER, voskService);
            voskInitialized = true;
            log.info("Vosk STT服务初始化成功");
        } catch (Exception e) {
            log.error("Vosk STT服务初始化失败", e);
            voskInitialized = false;
        }
    }

    /**
     * 获取默认STT服务
     * 如果Vosk可用则返回Vosk，否则返回备选服务
     */
    public SttService getDefaultSttService() {
        // 如果Vosk已初始化成功，直接返回
        if (voskInitialized && serviceCache.containsKey(DEFAULT_PROVIDER)) {
            return serviceCache.get(DEFAULT_PROVIDER);
        }
        SysLlmConfig config = sysLlmConfigService.queryDefaultLlmConfig(LlmConfigType.STT);
        // 对于API服务，使用"provider:configId"作为缓存键，确保每个配置使用独立的服务实例
        Long configId = config.getId();
        String cacheKey = config.getProvider() + ":" + (configId != null ? configId : "default");
        // 检查是否已有该配置的服务实例
        if (serviceCache.containsKey(cacheKey)) {
            return serviceCache.get(cacheKey);
        } else  {
            log.warn("没有可用的STT服务，将尝试创建默认API服务");
            try {
                SttService service = createApiService(config);
                if (service != null) {
                    serviceCache.put(cacheKey, service);
                    return service;
                }
                log.error("创建默认API服务失败");
                return null;
            } catch (Exception e) {
                log.error("创建默认API服务失败", e);
                return null;
            }
        }
    }

    /**
     * 根据配置获取STT服务
     */
    public SttService getSttService(SysLlmConfig config) {
        if (config == null) {
            return getDefaultSttService();
        }
        String provider = config.getProvider();
        // 如果是Vosk，直接使用全局共享的实例
        if (DEFAULT_PROVIDER.equals(provider)) {
            // 如果Vosk还未初始化，尝试初始化
            if (!voskInitialized && !serviceCache.containsKey(DEFAULT_PROVIDER)) {
                initializeVosk();
            }
            // Vosk初始化失败的情况
            if (!voskInitialized) {
                return null;
            }
            return serviceCache.get(DEFAULT_PROVIDER);
        }
        // 对于API服务，使用"provider:configId"作为缓存键，确保每个配置使用独立的服务实例
        Long configId = config.getId();
        String cacheKey = provider + ":" + (configId != null ? configId : "default");
        // 检查是否已有该配置的服务实例
        if (serviceCache.containsKey(cacheKey)) {
            return serviceCache.get(cacheKey);
        }
        // 创建新的API服务实例
        try {
            SttService service = createApiService(config);
            if (service != null) {
                serviceCache.put(cacheKey, service);
                return service;
            }
        } catch (Exception e) {
            log.error("创建{}服务失败, configId={}", provider, configId, e);
        }
        return null;
    }

    /**
     * 根据配置创建API类型的STT服务
     */
    private SttService createApiService(SysLlmConfig config) {
        if (config == null) {
            return null;
        }
        String provider = config.getProvider();
        // 根据提供商类型创建对应的服务实例
        if ("tencent".equals(provider)) {
            return new TencentSttService(config);
        } else if ("aliyun".equals(provider)) {
            return new AliyunSttService(config);
        } else if ("xfyun".equals(provider)) {
            return new XfyunSttService(config);
        }
        // 可以添加其他服务提供商的支持
        log.warn("不支持的STT服务提供商: {}", provider);
        return null;
    }

    /**
     * 移除缓存中的指定配置的服务实例
     * TODO 什么时候移除缓存？
     * @param config 配置对象
     */
    public void removeCache(SysLlmConfig config) {
        // 对于API服务，使用"provider:configId"作为缓存键，确保每个配置使用独立的服务实例
        Long configId = config.getId();
        String provider = config.getProvider();
        String configIdStr = (configId != null ? configId.toString() : "default");
        // 遍历缓存的所有键，找到匹配的键并移除
        serviceCache.keySet().removeIf(key -> {
            String[] parts = key.split(":");
            if (parts.length != 3) {
                return false;
            }
            String keyProvider = parts[0];
            String keyConfigId = parts[1];
            // 检查provider和configId是否匹配
            return keyProvider.equals(provider) && keyConfigId.equals(configIdStr);
        });

    }
}
